/**
 * 
 */
package view.impl.ingame.animation;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

import org.newdawn.slick.Animation;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;



import sharedGameLogic.enums.BattleDistance;
import view.impl.ingame.Fighter;
import view.impl.ingame.Fighter.Player;

/**
 * @author Julian
 *
 */
public class AnimationLoader {
	
	public static ActionAnimation loadAnimation(String folder, String name, Fighter owner) throws AnimationLoadException {
		boolean mirrored = owner.getPlayer() == Player.PLAYER2;
		Scanner sc = null;
		try {
			sc = new Scanner(new File(folder + "/" + name + ".txt"));
		} catch (FileNotFoundException e) {
			throw new AnimationLoadException("File not found: " + folder + "/" + name + ".txt");
		}
		
		EActionType type = EActionType.MOVE;
		int nrFrames = 0;
		double duration = 0;
		boolean pingPong = false;
		boolean looping = false;
		String effect = null;
		BattleDistance effectDist = null;
		int hitPosX = 0;
		int hitPosY = 0;
		int hitFrame = 0;
		int offsetX = 0;
		int offsetY = 0;
		
		// Load data.
		while(sc.hasNextLine()) {
			String[] nextLine = sc.nextLine().split(":");
			if(nextLine[0].trim().toLowerCase().equals("frames")) {
				nrFrames = Integer.parseInt(nextLine[1].trim());
				
			} else if(nextLine[0].trim().toLowerCase().equals("duration")) {
				duration = Double.parseDouble(nextLine[1].trim());
				
			} else if(nextLine[0].trim().toLowerCase().equals("pingPong")) {
				pingPong = Boolean.parseBoolean(nextLine[1].trim());
				
			} else if(nextLine[0].trim().toLowerCase().equals("looping")) {
				looping = Boolean.parseBoolean(nextLine[1].trim());
				
			} else if(nextLine[0].trim().toLowerCase().equals("type")) {
				if(nextLine[1].trim().toLowerCase().equals("attack")) {
					type = EActionType.ATTACK;
				} else if (nextLine[1].trim().toLowerCase().equals("move")) {
					type = EActionType.MOVE;
				}
			} else if(nextLine[0].trim().toLowerCase().equals("effect")) {
				effect = nextLine[1].trim().toLowerCase();
			
			} else if(nextLine[0].trim().toLowerCase().equals("effectDistance")) {
				String s = nextLine[1].trim().toLowerCase();
				if(s.equals("close")) {
					effectDist = BattleDistance.CLOSE_COMBAT;
				} else if(s.equals("range")) {
					effectDist = BattleDistance.DISTANCED_COMBAT;
				}
				
			} else if(nextLine[0].trim().toLowerCase().equals("hitpos")) {
				hitPosX = Integer.parseInt(nextLine[1].split(",")[0].trim());
				hitPosY = Integer.parseInt(nextLine[1].split(",")[1].trim());
				
			} else if(nextLine[0].trim().toLowerCase().equals("hitframe")) {
				hitFrame = Integer.parseInt(nextLine[1].trim());
				
			} else if(nextLine[0].trim().toLowerCase().equals("offset")) {
				offsetX = Integer.parseInt(nextLine[1].split(",")[0].trim());
				offsetY = Integer.parseInt(nextLine[1].split(",")[1].trim());
				
			}
			
			
		}
		
		
		// Instantiate objects.
		Image img = null;
		try {
			img = new Image(folder + "/" + name + ".png");
		} catch (SlickException e) {
			throw new AnimationLoadException("Unable to load image: " + folder + "/" + name + ".png\nDebug: " + e.getMessage());
		}
		
		
		SpriteSheet frames = new SpriteSheet(img, img.getWidth() / nrFrames, img.getHeight());
		Animation anim = null;
		if(!mirrored) {
			anim = new Animation(frames, (int) duration);
		} else {
			Image[] mirroredFrames = new Image[nrFrames];
			for(int i = 0; i < nrFrames; i++) {
				mirroredFrames[i] = frames.getSprite(i, 0).getFlippedCopy(true, false);
			}
			anim = new Animation(mirroredFrames, (int) duration);
		}
		
		anim.setPingPong(pingPong);
		anim.setLooping(looping);
		
		// Decide what to return.
		switch (type) {
		case ATTACK:
			try {
				return new AttackAction(anim, offsetX, offsetY, effect, hitPosX, hitPosY, hitFrame, effectDist, mirrored, owner);
			} catch (EffectLoadException e) {
				throw new AnimationLoadException("Unable to create new AttackAction.", e);
			}

			
		case MOVE:
			return new MoveAction(anim, offsetX, offsetY, mirrored);
			
		default:
			return null;
		}
	}
	
}
